package com.tfjybj.itoo.teach.provider.service.impl;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.dmsdbj.itoo.tool.base.service.impl.BaseServicePlusImpl;
import com.dmsdbj.itoo.tool.business.ItooResult;
import com.dmsdbj.itoo.tool.constantutil.YearSemester;
import com.dmsdbj.itoo.tool.uuid.BaseUuidUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tfjybj.itoo.teach.entity.CourseEntity;
import com.tfjybj.itoo.teach.entity.TeacherCourseEntity;
import com.tfjybj.itoo.teach.model.StaffModel;
import com.tfjybj.itoo.teach.model.TeacherCourseAndCourseModel;
import com.tfjybj.itoo.teach.model.TeacherCourseModel;
import com.tfjybj.itoo.teach.provider.dao.StaffDao;
import com.tfjybj.itoo.teach.provider.dao.TeacherCourseDao;
import com.tfjybj.itoo.teach.provider.service.CourseService;
import com.tfjybj.itoo.teach.provider.service.TeacherCourseService;
import com.tfjybj.itoo.teach.template.TeacherCourseTemplate;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.jplus.hyberbin.excel.utils.ExcelUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.util.*;

import static com.tfjybj.itoo.teach.provider.until.DemoConstants.*;

/**
 * TeacherCourseService接口实现类
 * ${base}表
 *
 * @author 田成荣
 * @version 2.0.0
 * @since 2.0.0 2018-11-08 19:34:10
 */
@Slf4j
@Service("teacherCourseService")
public class TeacherCourseServiceImpl extends BaseServicePlusImpl<TeacherCourseDao, TeacherCourseEntity> implements TeacherCourseService {

    //region 模板生成
    @Resource
    private TeacherCourseDao teacherCourseDao;
    @Resource
    private StaffDao staffDao;
    @Resource
    private CourseService courseService;
    @Resource
    private TeacherCourseService teacherCourseService;
    @Resource
    private RedisTemplate<String, TeacherCourseTemplate> redisTemplate;


    @Override
    public List<TeacherCourseModel> queryByLikeCourseId(String courseId) {
        return new LinkedList<TeacherCourseModel>(teacherCourseDao.queryLikeCourseId(courseId));
    }

    //endregion

    /* **********************************以下为非模板生成的内容********************************* */


    @Override
    public PageInfo<TeacherCourseEntity> queryTeacherCourseListByCourseId(String courseId) {
        return new PageInfo<>(teacherCourseDao.selectByCourseId(courseId));
    }

    @Override
    public PageInfo<TeacherCourseAndCourseModel> queryTeacherCourseAndCourse(String teacherId) {
        return new PageInfo<>(teacherCourseDao.selectByTeacherId(teacherId));
    }

    @Override
    public PageInfo<TeacherCourseModel> queryByTeacherIdAndCourseIdAndYear(String teacherId, String courseId, String schoolYear) {
        //学年学期转换成数字
        String schoolYears = YearSemester.getYearSemesterCodeByName(schoolYear);
        return new PageInfo<>(teacherCourseDao.selectByTeacherIdAndCourseIdAndYear(teacherId,courseId,schoolYears));
    }

    @Override
    public PageInfo<TeacherCourseModel> queryTeacherCourseByCodeAndNameStrLike (Integer pageNum, Integer pageSize, String strLike) {
        PageHelper.startPage(pageNum, pageSize);

        List<TeacherCourseModel> teacherCourseModelList = teacherCourseDao.selectByStrLike(strLike.trim());
        //将学年学期转化为中文
        for (TeacherCourseModel model : teacherCourseModelList){
            model.setSchoolYear(YearSemester.getYearSemesterNameByCode(model.getSchoolYear()));
        }

        //PageInfo<TeacherCourseModel> courseModelPageInfo = new PageInfo<>(teacherCourseModelList);
        return new PageInfo<>(teacherCourseModelList);
    }

    @Override
    public PageInfo<TeacherCourseModel> queryListByTeacherAndCourse(String courseName, String teacherName, String schoolYear, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        //学年学期转换成数字
        String schoolYears;
        if(StringUtils.isEmpty(schoolYear.trim())) {
            schoolYears = schoolYear;
        }else{
            schoolYears = YearSemester.getYearSemesterCodeByName(schoolYear);
        }

        List<TeacherCourseModel> teacherCourseModelList = teacherCourseDao.selectListByTeacherAndCourse(courseName.trim(),teacherName.trim(),schoolYears.trim());
        //将学年学期转化为中文
        for (TeacherCourseModel model : teacherCourseModelList){
            model.setSchoolYear(YearSemester.getYearSemesterNameByCode(model.getSchoolYear()));
        }

        //PageInfo<TeacherCourseModel> courseModelPageInfo = new PageInfo<>(teacherCourseModelList);
        return new PageInfo<>(teacherCourseModelList);
    }

    @Override
    public PageInfo<TeacherCourseModel> queryTeacherCourseByIds(@Param("list") List<String> ids) {
        return new PageInfo<>(teacherCourseDao.selectListByTeacherId(ids));
    }

    @Override
    public PageInfo<TeacherCourseModel> queryAllTeacherCourse(Integer pageNo, Integer pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        //获取教师授课信息
        List<TeacherCourseModel> teacherCourseModelList = teacherCourseDao.queryAllTeacherCourse();
        //将学年学期转化为中文
        for (TeacherCourseModel model : teacherCourseModelList){
            model.setSchoolYear(YearSemester.getYearSemesterNameByCode(model.getSchoolYear()));
        }

        //PageInfo<TeacherCourseModel> courseModelPageInfo = new PageInfo<>(teacherCourseModelList);
        return new PageInfo<>(teacherCourseModelList);
    }

    @Override
    public List<TeacherCourseModel> queryAllTeacherCourse() {
        //获取教师授课信息
        List<TeacherCourseModel> teacherCourseModelList = teacherCourseDao.queryAllTeacherCourse();
        //将学年学期转化为中文
        for (TeacherCourseModel model : teacherCourseModelList){
            model.setSchoolYear(YearSemester.getYearSemesterNameByCode(model.getSchoolYear()));
        }

        //List<TeacherCourseModel> courseModelPageInfo = new LinkedList<>(teacherCourseModelList);
        return new LinkedList<>(teacherCourseModelList);
    }

    @Override
    public boolean addList(TeacherCourseModel model) {


        List<TeacherCourseEntity> teacherCourseModelList = new LinkedList<>();//存储实体的List

        for (int i=0;i<model.getCourseIds().size();i++){
            for(int j=0;j<model.getTeacherIds().size();j++){
                TeacherCourseEntity teacherCourseEntity = new TeacherCourseEntity();
                teacherCourseEntity.setSchoolYear(YearSemester.getYearSemesterCode(0,0).get(0));//获取当前学年学期
                teacherCourseEntity.setIsComputer(model.getIsComputer());
                teacherCourseEntity.setIsMedia(model.getIsMedia());
                teacherCourseEntity.setTeacherId(model.getTeacherIds().get(j));
                teacherCourseEntity.setTeacherName(model.getTeacherNames().get(j));
                teacherCourseEntity.setCourseId(model.getCourseIds().get(i));
                teacherCourseEntity.setCourseName(model.getCourseNames().get(i));
                teacherCourseEntity.setId(IdWorker.getIdStr());
                //判断是否存在此条数据，将实体加入List类中
                if(teacherCourseDao.selectByCourseIdAndTeacherIdAndSchoolYear(teacherCourseEntity.getCourseId(),teacherCourseEntity.getTeacherId(),teacherCourseEntity.getSchoolYear()).size()>0){
                    return false;
                }else{
                    teacherCourseModelList.add(teacherCourseEntity);
                }
            }
        }
        return teacherCourseDao.insertAll(teacherCourseModelList);
    }

    @Override
    public ItooResult exportTeacherCourseInfo(HttpServletResponse response){

        // 需要导出的数据
        List<TeacherCourseModel> teacherCourseInfo = new ArrayList<>();

        teacherCourseInfo = teacherCourseService.queryAllTeacherCourse();
        // 转换字段
        teacherCourseInfo =this.changeValue(teacherCourseInfo);

        // 定义excel字段
        Map<Serializable,Serializable> map=new HashMap<>();
        map.put(SHEET_NAME,"教师授课信息");
        //要导出的字段
        map.put(COLUMNS,new String[]{"courseName","courseCode","schoolYear","teacherName","teacherCode","media","computer","remark"});
        //导出表格的标题
        map.put(TITLE,"教师授课信息");
        map.put(NAME,"教师授课信息表");

        //数据导入到模板
        List<TeacherCourseTemplate> teacherCourseTemplates = new ArrayList<>();
        for (TeacherCourseModel teacherCourseModel: teacherCourseInfo) {
            TeacherCourseTemplate teacherCourseTemplate = new TeacherCourseTemplate();
            BeanUtils.copyProperties(teacherCourseModel,teacherCourseTemplate);
            teacherCourseTemplates.add(teacherCourseTemplate);
        }

        //不为空进行导出
        if (teacherCourseTemplates.size() == 0){
            return ItooResult.build(ItooResult.FAIL,"没有要导出的数据");
        }
        map.put(DATA_LIST,(Serializable) teacherCourseTemplates);
        //导出
        try {
            ExcelUtil.exportExcel(map,response);
        } catch (Exception e) {
            log.error("导出失败,未知的异常--"+e);
            return ItooResult.build(ItooResult.FAIL, "导出信息失败！");
        }
        return ItooResult.build(ItooResult.SUCCESS  , "导出信息成功！");
    }

    private List<TeacherCourseModel> changeValue(List<TeacherCourseModel> teacherCourseInfo) {
        //更改IsComputer、Ismedia
        Map<String,String> map = new HashMap<>();
        map.put("1","是");
        map.put("0","否");

        for (int i = 0 ; i < teacherCourseInfo.size() ; i++){
            if(teacherCourseInfo.get(i).getIsMedia()!=null){
                String media =teacherCourseInfo.get(i).getIsMedia().toString();
                teacherCourseInfo.get(i).setMedia(map.get(media));
            }
            if(teacherCourseInfo.get(i).getIsComputer()!=null){
                String computer =teacherCourseInfo.get(i).getIsComputer().toString();
                teacherCourseInfo.get(i).setComputer(map.get(computer));
            }
        }
        return teacherCourseInfo;
    }

    /**
     * 下载模板-导入用
     *
     * @param response 响应
     * @return 下载成功或失败
     * @author 郄子硕
     * @since 2018-11-27 20:34:25
     */
    @Override
    public Boolean downTemplate(HttpServletResponse response){
        Map<Serializable,Serializable> map = new HashMap<>(16);
        List<TeacherCourseTemplate> templateList= new ArrayList<>();
        TeacherCourseTemplate teacherCourseExportTemplate = new TeacherCourseTemplate();
        teacherCourseExportTemplate.setTeacherCode("123456");
        teacherCourseExportTemplate.setTeacherName("张三");
        teacherCourseExportTemplate.setCourseCode("456789");
        teacherCourseExportTemplate.setCourseName("计算机基础");
        teacherCourseExportTemplate.setSchoolYear("2018-2019学年第一学期");
        teacherCourseExportTemplate.setMedia("是");
        teacherCourseExportTemplate.setComputer("否");
        teacherCourseExportTemplate.setRemark("备注");
        templateList.add(teacherCourseExportTemplate);
        //excel设置
        map.put(SHEET_NAME,"教师授课信息");
        map.put(COLUMNS,new String[]{"courseName","courseCode","schoolYear","teacherName","teacherCode","media","computer","remark"});
        map.put(TITLE,"教师授课信息表");
        map.put(NAME,"教师授课信息模板");
        map.put(DATA_LIST,(Serializable) templateList);

        try {
            ExcelUtil.exportExcel(map,response);
            return true;
        } catch (Exception e) {
            return false;
        }
    }


    /**
     * 导入教师信息
     *
     * @param multipartFile 批量导入的文件
     * @param request       请求
     * @param response      响应
     * @return itooresult 批量导入的结果
     * @author 张家豪
     * @since 2018.11.25 08:38
     */
    @Override
    public ItooResult importTeacherCourse(MultipartFile multipartFile, HttpServletRequest request, HttpServletResponse response){
        response.setContentType("UTF-8");
        try {
            String fileName = multipartFile.getOriginalFilename();
            if (fileName == null) {
                log.error("导入失败，fileName is null");
                return  ItooResult.build(ItooResult.FAIL,"传入的文件为空");
            }
            // excel解析成list
            Map<Serializable,Serializable> map = new HashMap<>(4);
            map.put(SHEET_NAME, "教师授课信息");
            map.put(CLASS, TeacherCourseTemplate.class);
            List<TeacherCourseTemplate> teacherCourseImportList = ExcelUtil.importExcel(Objects.requireNonNull(fileName),map,request,response);
            if (StringUtils.isEmpty(teacherCourseImportList)) {
                return ItooResult.build(ItooResult.FAIL,"导入的数据为空");
            }
            // 定义导入错误数据集合
            List<TeacherCourseTemplate> errorTeacherCourseList = new ArrayList<>();
            String errorListId = BaseUuidUtils.base58Uuid();
            Long size = redisTemplate.opsForZSet().size(errorListId);
            size = size == null ? 0L : size;
            // 循环处理数据
            for (TeacherCourseTemplate excelTeacherCourse: teacherCourseImportList){
                // 数据验证
                if (!this.verify(excelTeacherCourse)) {
                    TeacherCourseTemplate teacherCourseTemplate = new TeacherCourseTemplate();
                    BeanUtils.copyProperties(excelTeacherCourse,teacherCourseTemplate);
                    errorTeacherCourseList.add(teacherCourseTemplate);
                    redisTemplate.opsForZSet().add(errorListId, teacherCourseTemplate, size + 1);
                    continue;
                }
                TeacherCourseEntity teacherCourseEntity = new TeacherCourseEntity();
                BeanUtils.copyProperties(excelTeacherCourse,teacherCourseEntity);
                // 添加教师授课信息
                this.save(teacherCourseEntity);
            }
            // 不符合条件的信息返回
            if (errorTeacherCourseList.size()>0){
                return ItooResult.build("0001", "部分教师授课信息导入失败", errorListId);
//                Map<Serializable,Serializable> errorMap=new HashMap<>();
//                errorMap.put(NAME, "未导入的信息");
//                errorMap.put(SHEET_NAME, "教师授课信息");
//                errorMap.put(TITLE, "未导入的信息");
//                errorMap.put(COLUMNS,new String[]{"courseName","courseCode","schoolYear","teacherName","teacherCode","media","computer","remark","failReason"});
//                errorMap.put(DATA_LIST,(Serializable) errorTeacherCourseList);
//                ExcelUtil.exportExcel(errorMap,response);
//                return ItooResult.build(ItooResult.FAIL,"部分教师授课信息添加失败",errorTeacherCourseList);
            }
        } catch (Exception e) {
            return ItooResult.build(ItooResult.FAIL,"教师授课信息导入异常");
        }
        return ItooResult.build(ItooResult.SUCCESS,"教师授课信息导入成功");
    }

    /**
     * 批量导入前验证数据是否符合要求
     *
     * @param
     * @return
     * @author 张家豪
     * @since 2018.11.25 08:59
     */
    private boolean verify(TeacherCourseTemplate teacherCourseTemplate) {
        // 判断非空字段是否有值
        if (StringUtils.isEmpty(teacherCourseTemplate.getTeacherCode())|| StringUtils.isEmpty(teacherCourseTemplate.getCourseName())|| StringUtils.isEmpty(teacherCourseTemplate.getSchoolYear())|| StringUtils.isEmpty(teacherCourseTemplate.getTeacherName())){
            teacherCourseTemplate.setFailReason("学年学期、课程、教师名称、教师代码等信息不能为空");
            log.warn("导入失败，学年学期、课程、教师名称、教师代码等信息不能为空，导入信息-",teacherCourseTemplate);
            return false;
        }
        // 学年学期转换
        teacherCourseTemplate.setSchoolYear(YearSemester.getYearSemesterCodeByName(teacherCourseTemplate.getSchoolYear()));

            //根据课程名称查询课程是否存在
            List<CourseEntity> courseEntityList = courseService.findCourseByName(teacherCourseTemplate.getCourseName());
            if (courseEntityList == null || courseEntityList.isEmpty()) {
                teacherCourseTemplate.setFailReason("课程" + teacherCourseTemplate.getCourseName() + "不存在");
                log.warn("导入失败，课程名称存在，导入信息-",teacherCourseTemplate);
                return false;
            }
            teacherCourseTemplate.setCourseId(courseEntityList.get(0).getId());

            //根据教师Code查询教师是否存在
            List<StaffModel> staffModel = staffDao.queryByCode(teacherCourseTemplate.getTeacherCode());

            if (staffModel == null||staffModel.size() == 0) {
                teacherCourseTemplate.setFailReason("教师" + teacherCourseTemplate.getTeacherName() + "不存在");
                log.warn("导入失败，教师不存在，导入信息-",teacherCourseTemplate);
                return false;
            } else if (!staffModel.get(0).getName().equals(teacherCourseTemplate.getTeacherName())) {
                teacherCourseTemplate.setFailReason("教师" + teacherCourseTemplate.getTeacherName() + "与表格中的code不对应");
                log.warn("导入失败，教师与表格中的code不对应，导入信息-",teacherCourseTemplate);
                return false;
            }
            teacherCourseTemplate.setTeacherId(staffModel.get(0).getId());
        // 判断该学年是否已存在该教师授该门课
        if (teacherCourseDao.selectByTeacherIdAndCourseIdAndYear(teacherCourseTemplate.getTeacherId(),teacherCourseTemplate.getCourseId(),teacherCourseTemplate.getSchoolYear()).size()>0) {
            teacherCourseTemplate.setFailReason("该教师授课记录已存在");
            log.warn("导入失败，教师授课记录已存在，导入信息-",teacherCourseTemplate);
            return false;
        }

        return true;
    }

    @Override
    public boolean downErrorList(String errorListId, HttpServletResponse response) {
        // redis 取出没有成功导入的人员信息
        Set set = redisTemplate.opsForZSet().range(errorListId, 0, -1);
        ArrayList teacherCourseTemplates = new ArrayList<>(set);
        // 清空redis数据
        redisTemplate.delete(errorListId);

        //导出
        if (teacherCourseTemplates.size() == 0) {
            return false;
        }
        Map<Serializable, Serializable> errorMap = new HashMap<>(16);
        errorMap.put(NAME, "教师授课未导入信息-" + System.currentTimeMillis());
        errorMap.put(SHEET_NAME, "教师授课信息");
        errorMap.put(TITLE, "未导入的信息");
        errorMap.put(COLUMNS,new String[]{"courseName","courseCode","schoolYear","teacherName","teacherCode","media","computer","remark","failReason"});
        errorMap.put(DATA_LIST, (Serializable) teacherCourseTemplates);
        try {
            ExcelUtil.exportExcel(errorMap, response);
        } catch (Exception e) {
            return false;
        }
        return true;
    }



}
